import { Injectable, Logger } from '@nestjs/common';
import { BaseResponse } from '../base-response';

@Injectable()
export class CaptchaService {
  private readonly logger = new Logger(CaptchaService.name);
  private readonly LIVE_TIME = 10 * 60 * 1000;
  private captchaCodeMap: Map<string, CaptchaCode>;

  constructor() {
    this.captchaCodeMap = new Map();
  }

  /**
   * 生成随机码并发送邮箱
   * @param email
   */
  async generateCode(email: string): Promise<BaseResponse> {
    this.randomCode(email);
    // TODO send captcha code to email
    return {
      isSuccess: true
    };
  }

  async checkCode(email: string, code: number): Promise<BaseResponse> {
    const captcha = this.captchaCodeMap.get(email);
    if (!captcha) {
      return {
        isSuccess: false,
        message: '验证码不存在'
      };
    }

    const nowTime = new Date().getTime();
    if (nowTime - captcha.createTime > this.LIVE_TIME) {
      this.captchaCodeMap.delete(email);
      return {
        isSuccess: false,
        message: '验证码过期'
      };
    }

    if (captcha.code !== code) {
      return {
        isSuccess: false,
        message: '验证码错误'
      };
    }

    this.captchaCodeMap.delete(email);
    return { isSuccess: true };
  }

  /**
   * 删除过期验证码
   */
  clearOutDateCode(): void {
    const outDateEmails = [];
    const nowTime = new Date().getTime();
    this.captchaCodeMap.forEach((code, email) => {
      if (nowTime - code.createTime > this.LIVE_TIME) {
        outDateEmails.push(email);
      }
    });

    outDateEmails.forEach((email) => {
      this.captchaCodeMap.delete(email);
    });
  }

  /**
   * 生成随机码，并记录生成时间
   * @param email
   * @private
   */
  private randomCode(email: string): number {
    const randomNum = (length = 6) => {
      const maxNum = Math.pow(10, length);
      const minNum = Math.pow(10, length - 1);
      return Math.floor(Math.random() * (maxNum - minNum) + minNum);
    };

    const code = randomNum();
    this.logger.debug('captcha code is:', code);
    this.captchaCodeMap.set(email, {
      createTime: new Date().getTime(),
      code
    });
    return code;
  }
}

interface CaptchaCode {
  createTime: number;
  code: number;
}
